package model;

/**
 * The RectangularArea class represents a rectangle and allows the modification of the 
 * position, height and width.
 *
 */
abstract public class RectangularArea extends Observee{
	
	private Point leftUpperCorner;
	private int width;
	private int height;
	
	/**
	 * Constructor of RectangularArea.
	 * @param position is the position of the top left corner of this RectangularArea.
	 * @param width is the width of this RectangularArea.
	 * @param height is the height of this RectangularArea.
	 */
	protected RectangularArea(final Point position, final int width, final int height) {
		this.setLeftUpperCorner(position);
		this.setWidth(width < 0 ? 0 :width);
		this.setHeight(height < 0 ? 0 : height);
	}
	public int getHeight() {
		return height;
	}
	private void setHeight(final int height) {
		this.height = height;
	}
	public Point getLeftUpperCorner() {
		return leftUpperCorner;
	}
	public Point getRightUpperCorner() {
		return new Point(this.getLeftUpperCorner().getX() + this.getWidth(),this.getLeftUpperCorner().getY());
	}
	public Point getLeftLowerCorner() {
		return new Point(this.getLeftUpperCorner().getX(),this.getLeftUpperCorner().getY() + this.getHeight());
	}
	public Point getRightLowerCorner() {
		return new Point(this.getLeftUpperCorner().getX() + this.getWidth(), this.getLeftUpperCorner().getY() + this.getHeight());
	}
	public int getTop(){
		return this.getLeftUpperCorner().getY();
	}
	public int getBottom(){
		return this.getLeftLowerCorner().getY();
	}
	public int getLeft(){
		return this.getLeftUpperCorner().getX();
	}
	public int getRight(){
		return this.getRightUpperCorner().getX();
	}
	private void setLeftUpperCorner(final Point leftUpperCorner) {
		this.leftUpperCorner = leftUpperCorner;
	}
	public int getWidth() {
		return width;
	}
	private void setWidth(final int width) {
		this.width = width;
	}
	public void move(final int deltaX, final int deltaY){
		this.getLeftUpperCorner().move(deltaX, deltaY);
	}
	/**
	 * Resizes this RectangularArea to the provided width and height
	 * @param width is the new width.
	 * @param height is the new height.
	 * @throws NegativeLengthException if the provided width and height is less than or equal to zero.
	 */
	public void resize(final int width, final int height) throws NegativeLengthException{
		if (width <= 0) throw new NegativeLengthException();
		if (height <= 0) throw new NegativeLengthException();
		this.setHeight(height);
		this.setWidth(width);
	}
	@Override
	public String toString(){
		return  "(WIDTH: " + this.getWidth() + ", HEIGHT: " + this.getHeight() + ") at " + this.getLeftUpperCorner();
	}
	
	/**
	 * Provides whether the provided RectangularArea is inside of this RectangularArea or
	 * both areas have the same dimensions and position.
	 * @param area is the other area.
	 * @return true if the provided RectanguarArea is inside of this RectangularArea.
	 */
	public abstract boolean isIn(RectangularArea area);
	
	/**
	 * Returns true, if the provided area overlaps into this area.
	 * @param area is the RectangularArea that is checked.
	 * @return true, if the provided area overlaps into this area. Else false.
	 */
	public boolean overlaps(final RectangularArea area){
		return this.getLeftUpperCorner().getX() < area.getRightLowerCorner().getX() &&
				this.getRightLowerCorner().getX() > area.getLeftUpperCorner().getX() &&
				this.getLeftUpperCorner().getY() < area.getRightLowerCorner().getY() &&
				this.getRightLowerCorner().getY() > area.getLeftUpperCorner().getY();
	}	
	
}